Week 10: Output Devices

DHT22 Sensor  →  SSD1306 OLED Display  +  NeoPixel Humidity Indicator

I²C 1-WIRE 3.3 V / 5 V WS2812B


01 — Overview

This week I explored output devices by building a real-time environmental monitor driven by a DHT22 temperature and humidity sensor. The sensor feeds two independent output peripherals simultaneously:

Microcontroller (ESP32 / Arduino) DHT22 Temp + Humidity DATA (1-wire) SSD1306 OLED 128×64 · I²C SDA / SCL NeoPixel ×4 WS2812B · DIN DIN (330Ω series)

02 — Components

🌡 DHT22 (AM2302)

Capacitive humidity + NTC temperature sensor. Single-wire proprietary protocol. Range: 0–100 % RH, −40–80 °C. Accuracy: ±2 % RH, ±0.5 °C. Minimum 2 s between readings.

📺 SSD1306 OLED 0.96″

128×64 pixel monochrome OLED. I²C interface at address 0x3C (some modules use 0x3D). Operates at 3.3 V or 5 V. Self-emissive — no backlight, excellent contrast in dim environments.

💡 WS2812B NeoPixel ×4

Addressable RGB LEDs daisy-chained on a single data line. 5 V, up to 60 mA per LED at full white. Controlled via Adafruit NeoPixel library. No extra clock wire needed.

🖥 Microcontroller

ESP32 or Arduino Uno. ESP32 preferred — built-in I²C on GPIO 21/22, 3.3 V logic, and Wi-Fi for optional remote logging. Either board works at 3.3 V or 5 V.

⚡ Passives

10 kΩ pull-up resistor on DHT22 DATA line to VCC. 300–500 Ω series resistor on NeoPixel DIN to suppress signal ringing on long wire runs.

🔋 Power Budget

OLED ≈ 20 mA. NeoPixels at 80/255 brightness ≈ 80 mA total. DHT22 ≈ 1.5 mA. Total ≈ 102 mA — USB power from the development board is sufficient.


03 — Wiring & Pinout

DHT22 → Microcontroller

DHT22 Pin Connect To Notes
1 — VCC 3.3 V or 5 V Match your board's logic voltage
2 — DATA GPIO 4 (any digital pin) Add 10 kΩ pull-up resistor from DATA to VCC
3 — NC Leave unconnected
4 — GND GND Shared ground with MCU

SSD1306 OLED → Microcontroller (I²C)

OLED Pin ESP32 Arduino Uno
VCC 3.3 V 5 V
GND GND GND
SDA GPIO 21 A4
SCL GPIO 22 A5

NeoPixel Strip → Microcontroller

NeoPixel Pin Connect To Notes
+5 V 5 V rail Must be 5 V — not 3.3 V
GND GND (shared) Common ground with MCU
DIN GPIO 5 via 330 Ω Series resistor placed close to the strip

⚠ LEVEL SHIFTING: ESP32 outputs 3.3 V logic. NeoPixels nominally require 5 V on DIN. In practice 3.3 V usually works, but if LEDs glitch or show wrong colours, add a 74AHCT125 level shifter between GPIO and DIN.

💡 TIP: Place a 100 µF electrolytic capacitor across the 5 V and GND pads of the NeoPixel strip to smooth power spikes and protect the first LED from inrush current.


04 — Program Logic

The firmware loop runs every 2 seconds — the minimum safe polling interval for the DHT22.

Read DHT22
Validate (NaN check)
Update OLED
Map humidity → colour
Write NeoPixels
Serial debug
delay(2000)

NeoPixel Humidity Colour Mapping

0 – 30% RH — Blue Very dry
30 – 60% RH — Green Comfortable
60 – 80% RH — Yellow Humid
80 – 100% RH — Red Very humid

All four LEDs display the same colour simultaneously to form a clear visual band. Brightness is set to 80/255 (~31%) to be eye-safe and keep current draw within USB limits.


05 — Code

Written for Arduino IDE. Tested on ESP32 and Arduino Uno. See Section 06 for library installation.

#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_NeoPixel.h>

// ── Pin definitions ────────────────────────────────────────
#define DHT_PIN 4 // DHT22 DATA pin
#define DHT_TYPE DHT22
#define NEO_PIN 5 // NeoPixel DIN pin
#define NEO_COUNT 4 // Number of LEDs
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // -1 = share Arduino reset pin
#define OLED_ADDR 0x3C // Try 0x3D if display is blank

// ── Object instances ───────────────────────────────────────
DHT dht(DHT_PIN, DHT_TYPE);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_NeoPixel strip(NEO_COUNT, NEO_PIN, NEO_GRB + NEO_KHZ800);

// ── Humidity → RGB colour ──────────────────────────────────
uint32_t humidityColour(float h) {
  if (h < 30) return strip.Color(0, 0, 200); // Blue — very dry
  if (h < 60) return strip.Color(0, 200, 0); // Green — comfortable
  if (h < 80) return strip.Color(200, 150, 0); // Yellow — humid
  return strip.Color(200, 0, 0); // Red — very humid
}

void setup() {
  Serial.begin(115200);
  dht.begin();

  // NeoPixel initialisation
  strip.begin();
  strip.setBrightness(80); // ~31% — eye-safe & USB-friendly
  strip.show(); // all off at startup

  // OLED initialisation
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println("SSD1306 not found — check wiring!");
    while (1); // halt so error is visible in Serial Monitor
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Initialising...");
  display.display();
  delay(1000);
}

void loop() {
  float temp = dht.readTemperature(); // Celsius
  float hum = dht.readHumidity();

  // Validate — DHT22 returns NaN on read failure
  if (isnan(temp) || isnan(hum)) {
    Serial.println("DHT22 read failed — check pull-up resistor!");
    delay(2000);
    return;
  }

  // ── OLED update ─────────────────────────────────────────
  display.clearDisplay();

  display.setTextSize(2);
  display.setCursor(0, 0);
  display.print("T: ");
  display.print(temp, 1);
  display.println(" C");

  display.setCursor(0, 28);
  display.print("H: ");
  display.print(hum, 1);
  display.println(" %");

  display.setTextSize(1);
  display.setCursor(0, 56);
  display.print("Output Devices — Week 10");

  display.display(); // push framebuffer to screen

  // ── NeoPixel update ──────────────────────────────────────
  uint32_t col = humidityColour(hum);
  for (int i = 0; i < NEO_COUNT; i++) {
    strip.setPixelColor(i, col);
  }
  strip.show();

  // ── Serial debug ─────────────────────────────────────────
  Serial.printf("Temp: %.1f°C Hum: %.1f%%\n", temp, hum);

  delay(2000); // DHT22 minimum safe polling interval
}

06 — Libraries

Install all five via Sketch → Include Library → Manage Libraries in the Arduino IDE.

Library Author Purpose
DHT sensor library Adafruit Read temperature & humidity from DHT22
Adafruit Unified Sensor Adafruit Required dependency for the DHT library
Adafruit SSD1306 Adafruit Drive the SSD1306 OLED over I²C
Adafruit GFX Library Adafruit Graphics primitives — text, shapes, bitmaps
Adafruit NeoPixel Adafruit Control WS2812B addressable LEDs

💡 TIP: When you install DHT sensor library, the IDE will prompt you to also install Adafruit Unified Sensor — click "Install All" to grab both at once.


07 — Process & Photos

01

Breadboard Layout

Placed the DHT22 with its 10 kΩ pull-up, the OLED on the I²C bus, and ran the NeoPixel DIN through a 330 Ω resistor. Verified all shared grounds before powering up.

02

OLED First Boot

Uploaded a basic SSD1306 hello-world sketch to confirm the I²C address and verify the display worked before integrating the DHT22 and NeoPixels.

03

DHT22 Integration

Added sensor readings and confirmed valid output in Serial Monitor. Tested the NaN guard by briefly disconnecting the data wire.

04

NeoPixel Colour Mapping

Tested the four humidity bands by breathing on the sensor to raise humidity (green → yellow → red) and using a fan to dry it out (blue). Adjusted colour thresholds accordingly.

Demo Video

[ Replace with your <video> tag or embed ]


08 — Troubleshooting

?

DHT22 returns NaN

Check the 10 kΩ pull-up on DATA. Ensure at least 2 s between readings — the DHT22 is slow by design. Try a different GPIO pin and confirm you declared the correct DHT_TYPE.

?

OLED shows nothing

Run an I²C scanner sketch to find the actual address — some modules ship at 0x3D, not 0x3C. Confirm SDA and SCL are not swapped. Make sure display.display() is called — the framebuffer won't render without it.

?

NeoPixels flicker or show wrong colours

Add a 300–500 Ω resistor in series with DIN, placed close to the strip. Add a 100 µF cap across 5 V / GND at the strip. If using ESP32 at 3.3 V, add a 74AHCT125 level shifter.

?

Only first NeoPixel lights up

The strip is likely wired backwards — DIN and DOUT are directional. Check the arrow printed on the strip's PCB and ensure signal flows from MCU into the DIN end.


09 — Reflection

[ Write your personal reflection here. Some prompts to help: ]


10 — Files


← Back to Main Page